home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / editor / chktex.lha / chktex / source / FindErrs.c < prev    next >
C/C++ Source or Header  |  1996-01-25  |  15KB  |  703 lines

  1. /*
  2.  *  ChkTeX v1.2, error searching & report routines.
  3.  *  Copyright (C) 1995-96 Jens T. Berger Thielemann
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  Contact the author at:
  20.  *        Jens Berger
  21.  *        Spektrumvn. 4
  22.  *        N-0666 Oslo
  23.  *        Norway
  24.  *        E-mail: <jensthi@ifi.uio.no>
  25.  *
  26.  *
  27.  */
  28.  
  29. #include "ChkTeX.h"
  30.  
  31.  
  32.  
  33. /*
  34.  * Prints the status/conclusion after doing all the testing, including
  35.  * bracket stack status, math mode, etc.
  36.  */
  37.  
  38. void PrintStatus(ULONG Lines)
  39. {
  40.     ULONG                Cnt;
  41.     struct    CharInfo    *ci;
  42.  
  43.  
  44.     if(ci = PopChar(&CharStack))
  45.     {
  46.         do
  47.         {
  48.             PrintError(ci->LineBuf, ci->Column - 1, 1, ci->Line,
  49.                         emNoMatchC,
  50.                         ci->Char);
  51.             free(ci);
  52.         } while(ci = PopChar(&CharStack));
  53.     }
  54.  
  55.     if(MathMode)
  56.     {
  57.         PrintError(NULL, 0L, 0L, Lines,
  58.                     emMathStillOn);
  59.     }
  60.  
  61.     for(Cnt = 0L; Cnt < (NUMBRACKETS>>1); Cnt++)
  62.     {
  63.         if(Brackets[Cnt << 1] != Brackets[(Cnt << 1) + 1])
  64.         {
  65.             PrintError(NULL, 0L, 0L, Lines,
  66.                     emNoMatchCC,
  67.                     BrOrder[Cnt<<1], BrOrder[(Cnt<<1) + 1]);
  68.         }
  69.     }
  70.  
  71.     if(Verbosity > vbSilent)
  72.     {
  73.         fprintf(OutputFile, "%ld error(s) printed; %ld warnings printed; %ld user suppressed warnings.\n",
  74.                 ErrPrint, WarnPrint, UserSupp);
  75.     }
  76. }
  77.  
  78.  
  79. /*
  80.  * Searches the `Buf' for possible errors, and prints the errors. `Line'
  81.  * is supplied for error printing.
  82.  */
  83.  
  84. BOOL FindErr(const STRPTR RealBuf, const ULONG Line)
  85. {
  86.     STRPTR    BufPtr,                    /* Read pointer in buffer                    */
  87.             CmdPtr,                    /* We'll have to copy each command out.        */
  88.             PrePtr,                    /* Ptr to char in front of command, NULL if
  89.                                      * the cmd appears as the first character    */
  90.             TmpPtr,                    /* Temporary pointer                        */
  91.             ErrPtr,                    /* Ptr to where an error started            */
  92.             LineCpy = NULL;            /* In some cases, we may wish to strdup()    */
  93.     BOOL    FirstRun,                /* To handle solo `\'s as a special case    */
  94.             ReRun,                    /* Whether we should read a new character    */
  95.             OnceMore = TRUE;        /* Whether we'll run through the loop again    */
  96.     UBYTE    TmpC,                    /* Just a temp var used throughout the proc.*/
  97.             Char;                    /* Char. currently processed                */
  98.     ULONG    BrOffset,                /* Offset into BrOrder array                */
  99.             TmpCount,                /* Just for misc. counting.                    */
  100.             CmdLen;                    /* Length of misc. things                    */
  101.  
  102.     int        (*cb)(int c);            /* Callback hook                            */
  103.  
  104.     struct CharInfo    *ci;
  105. static const                        /* Characters we'll do some magic with        */
  106.     UBYTE    MgcChars [] = "$\\{}[]()-^_\"´`\'.";
  107.  
  108.  
  109.     NEWBUF(Buf, BUFLEN);
  110.  
  111.     if(RealBuf)
  112.     {
  113.         strcpy(Buf, RealBuf);
  114.  
  115.         TmpPtr = BufPtr = Buf;
  116.  
  117.         /* First, kill comments. */
  118.  
  119.         while(TmpPtr = strchr(TmpPtr, '%'))
  120.         {
  121.             if(TmpPtr[-1] != '\\')
  122.             {
  123.                 PrintError(RealBuf, TmpPtr - Buf, 1, Line,
  124.                             emComment);
  125.                 *TmpPtr = 0;
  126.                 break;
  127.             }
  128.             TmpPtr++;
  129.         }
  130.  
  131.  
  132.         /* Then, kill `\verb' commands */
  133.  
  134.         if(WipeVerb)
  135.         {
  136.             PrePtr = Buf;
  137.             while(PrePtr = strstr(PrePtr, "\\verb"))
  138.             {
  139.                 TmpC = PrePtr[5];
  140.                 if(!isalpha(TmpC) && TmpC)
  141.                 {
  142.                     if(TmpPtr = strchr(&PrePtr[6], TmpC))
  143.                         sfmemset(PrePtr, VERBCLEAR, (LONG) (TmpPtr - PrePtr) + 1);
  144.                     else
  145.                         PrintError(RealBuf, PrePtr - Buf, 5, Line,
  146.                                     emNoArgFound,
  147.                                     "\\verb");
  148.                 }
  149.                 PrePtr++;
  150.             }
  151.         }
  152.  
  153.         BufPtr = Buf;
  154.  
  155.         while(OnceMore && (BufPtr = strpbrk(BufPtr, MgcChars)))
  156.         {
  157.             PrePtr = BufPtr - 1;
  158.  
  159.             Char        = *BufPtr++;
  160.  
  161.             do
  162.             {
  163.                 CmdPtr        = CmdBuffer;
  164.                 FirstRun    = TRUE;
  165.  
  166.                 ReRun = FALSE;
  167.                 switch(Char)
  168.                 {
  169.                 case '.':
  170.                 case '\'':
  171.                 case '`':
  172.                     if((Char == *BufPtr) && (Char == BufPtr[1]))
  173.                     {
  174.                         if(Char == '.')
  175.                             PrintError(RealBuf, BufPtr - Buf - 1, 3, Line,
  176.                                     emEllipsis);
  177.                         else
  178.                             PrintError(RealBuf, BufPtr - Buf - 1, 3, Line,
  179.                                     emThreeQuotes,
  180.                                     Char, Char, Char,
  181.                                     Char, Char, Char);
  182.                     }
  183.  
  184.                     break;
  185.                 case '\"':
  186.                     PrintError(RealBuf, BufPtr - Buf - 1, 1, Line,
  187.                                 emUseQuoteLiga);
  188.                     break;
  189.  
  190.                 case '´':
  191.                     PrintError(RealBuf, BufPtr - Buf - 1, 1, Line,
  192.                                 emUseOtherQuote);
  193.                     break;
  194.  
  195.                 case '_':
  196.                 case '^':
  197.                     if(*PrePtr != '\\')
  198.                     {
  199.                         TmpPtr = PrePtr;
  200.                         while(TmpC = *TmpPtr--)
  201.                         {
  202.                             ifn(LATEX_SPACE(TmpC))
  203.                                 break;
  204.                         }
  205.  
  206.                         CmdLen = 1;
  207.  
  208.                         switch(TmpC)
  209.                         {
  210. /*{*/                    case '}':
  211.                             if(PrePtr[-1] != '\\')
  212.                                 break;
  213.                             CmdLen++;
  214.                             PrePtr--;
  215.                             /* FALLTHRU */
  216. /*[(*/                    case ')':
  217.                         case ']':
  218.                         case 0:
  219.                                 PrintError(RealBuf, PrePtr - Buf, CmdLen, Line,
  220.                                     emEnclosePar);
  221.                             break;
  222.                         }
  223.  
  224.                         if(TmpPtr = strip(BufPtr, STRP_LFT))
  225.                         {
  226.                             ErrPtr = TmpPtr;
  227.  
  228.                             if(isalpha(*TmpPtr))
  229.                                 cb = &isalpha;
  230.                             elif(isdigit(*TmpPtr))
  231.                                 cb = &isdigit;
  232.                             else
  233.                                 break;
  234.  
  235.                             while((*cb)(*TmpPtr++))
  236.                                 ;
  237.                             TmpPtr--;
  238.  
  239.                             if((TmpPtr - ErrPtr) > 1)
  240.                                 PrintError(RealBuf, ErrPtr - Buf, TmpPtr - ErrPtr, Line,
  241.                                     emEmbrace);
  242.                         }
  243.                     }
  244.                     break;
  245.                 case '-':
  246.                     ifn(MathMode)
  247.                     {
  248.                         for(TmpCount = 1;
  249.                             *BufPtr++ == '-';
  250.                             TmpCount++)
  251.                             ;
  252.  
  253.  
  254.                         if(    (LATEX_SPACE(*PrePtr) && LATEX_SPACE(*BufPtr) && (TmpCount != 3)) ||
  255.                             (isdigit(*PrePtr)      && isdigit(*BufPtr)      && (TmpCount != 2)) ||
  256.                             (isalpha(*PrePtr)      && isalpha(*BufPtr)      && (TmpCount != 1)))
  257.                         {
  258.                             PrintError(RealBuf, PrePtr - Buf + 1, TmpCount, Line,
  259.                                 emWrongDash);
  260.                         }
  261.                         BufPtr--;
  262.                     }
  263.                     break;
  264.                 case '\\':            /* Command encountered    */
  265.                     *CmdPtr++    = Char;
  266.                     *CmdPtr        = 0;
  267.  
  268.                     while(Char = *BufPtr++)
  269.                     {
  270.                         ifn(isalpha(Char) || (AtLetter && (Char == '@')))
  271.                         {
  272.                             ifn(FirstRun)
  273.                             {
  274.                                 if(!MathMode)
  275.                                 {
  276.                                     if(LATEX_SPACE(Char) && (!HasWord(CmdBuffer, &Silent)))
  277.                                     {
  278.                                         PrintError(RealBuf, BufPtr - Buf - 1,
  279.                                             1, Line,
  280.                                             emSpaceTerm);
  281.                                     }
  282.                                     elif((Char == '\\') && (!isalpha(*BufPtr)) && (!LATEX_SPACE(*BufPtr)))
  283.                                     {
  284.                                         PrintError(RealBuf, BufPtr - Buf - 1,
  285.                                             2, Line,
  286.                                             emNotIntended);
  287.                                     }
  288.                                 }
  289.                             }
  290.                             else
  291.                             {
  292.                                 *CmdPtr++    = Char;
  293.                                 *CmdPtr        = 0;
  294.                                 Char         = *BufPtr++;
  295.                             }
  296.  
  297.                             /* We've now isolated the command */
  298.  
  299.                             if(LATEX_SPACE(*PrePtr))
  300.                             {
  301.                                 if(HasWord(CmdBuffer, &Linker))
  302.                                     PrintError(RealBuf, PrePtr - Buf, 1, Line,
  303.                                         emNBSpace);
  304.                                 if(HasWord(CmdBuffer, &PostLink))
  305.                                     PrintError(RealBuf, PrePtr - Buf, 1, Line,
  306.                                         emFalsePage);
  307.                             }
  308.  
  309.                             if(HasWord(CmdBuffer, &IJAccent))
  310.                             {
  311.                                 if(TmpPtr = GetLTXArg(&BufPtr[-1], TmpBuffer, '{')) /*}*/
  312.                                 {
  313.                                     if(TmpPtr = strpbrk(TmpPtr, "ij"))
  314.                                     {
  315.                                         if(TmpPtr[-1] != '\\')
  316.                                             PrintError(RealBuf, PrePtr - Buf + 1, (LONG) strlen(CmdBuffer), Line,
  317.                                                 emAccent,
  318.                                                 CmdBuffer, *TmpPtr, MathMode? "math" : "");
  319.                                     }
  320.                                 }
  321.                                 else
  322.                                 {
  323.                                     PrintError(RealBuf, PrePtr - Buf + 1, (LONG) strlen(CmdBuffer),
  324.                                         Line,
  325.                                         emNoArgFound,
  326.                                         CmdBuffer);
  327.                                 }
  328.                             }
  329.  
  330.                             if(HasWord(CmdBuffer, &Italic))
  331.                                 ItState = itOn;
  332.  
  333.                             /*
  334.                              * Got to do this one here, so we can give error
  335.                              * position. Should really belong to PerformCommand().
  336.                              */
  337.  
  338.                             if(!strcmp(CmdBuffer, "\\/"))
  339.                             {
  340.                                 switch(ItState)
  341.                                 {
  342.                                 case itOn:
  343.                                     ItState = itCorrected;
  344.                                     break;
  345.                                 case itCorrected:
  346.                                     PrintError(RealBuf, PrePtr - Buf + 1, 2, Line,
  347.                                         emItDup);
  348.                                     break;
  349.                                 case itOff:
  350.                                     PrintError(RealBuf, PrePtr - Buf + 1, 2, Line,
  351.                                         emItInNoIt);
  352.                                 }
  353.                             }
  354.  
  355.  
  356.                             PerformCommand(CmdBuffer);
  357.                             break;
  358.                         }
  359.                         else
  360.                         {
  361.                             *CmdPtr++    = Char;
  362.                             *CmdPtr        = 0;
  363.                         }
  364.                         FirstRun = FALSE;
  365.                     }
  366.  
  367.                     ReRun = TRUE;
  368.                     PrePtr = BufPtr - 2;
  369.                     break;
  370.                 case '}':
  371.                     if(*PrePtr != '\\')
  372.                     {
  373.                         if(ItState == itOn)
  374.                             PrintError(RealBuf, PrePtr - Buf + 1, 1, Line,
  375.                                         emNoItFound);
  376.  
  377.                         ItState = itOff;
  378.                     }
  379.                     /* FALLTHRU */
  380.                 case '(':
  381.                 case '[':
  382.                 case '{':
  383.  
  384.                 case ')':
  385.                 case ']':
  386.                     AddBracket(Char);
  387.  
  388.                     if((BrOffset = BrackIndex(Char)) != ~0UL)
  389.                     {
  390.                         if(BrOffset & 1)    /* Closing bracket of some sort    */
  391.                         {
  392.                             if(ci = PopChar(&CharStack))
  393.                             {
  394.                                 TmpC = MatchBracket(ci->Char);
  395.                                 free(ci);
  396.                             }
  397.                             else
  398.                                 TmpC = 0;
  399.  
  400.                             if(TmpC != Char)
  401.                             {
  402.                                 if(TmpC)
  403.                                     PrintError(RealBuf, BufPtr - Buf - 1, 1, Line,
  404.                                                 emExpectC,
  405.                                                 TmpC, Char);
  406.                                 else
  407.                                     PrintError(RealBuf, BufPtr - Buf - 1, 1, Line,
  408.                                                 emSoloC,
  409.                                                 Char);
  410.                             }
  411.  
  412.                         }
  413.                         else                /* Opening bracket of some sort    */
  414.                         {
  415.                             if(!LineCpy)
  416.                                 LineCpy = strdup(RealBuf);
  417.  
  418.                             if(LineCpy)
  419.                             {
  420.                                 ifn(PushChar(Char, Line, BufPtr - Buf, &CharStack, LineCpy))
  421.                                     PrintPrgErr(pmNoStackMem);
  422.                             }
  423.                             else
  424.                                 PrintPrgErr(pmStrDupErr);
  425.                         }
  426.                     }
  427.                     break;
  428.                 case '$':
  429.                     if(*PrePtr != '\\')
  430.                     {
  431.                         if(*BufPtr == '$')
  432.                             BufPtr++;
  433.                         MathMode ^= TRUE;
  434.                     }
  435.  
  436.                     break;
  437.                 default:
  438.                     ReRun = FALSE;
  439.                     break;
  440.                 }
  441.             } while(ReRun);
  442.         }
  443.  
  444.         /* Search for abbrevs... */
  445.  
  446.         strcpy(TmpBuffer, Buf);
  447.         strupr(TmpBuffer);
  448.  
  449.         for(TmpCount = 0L;
  450.             TmpCount < Abbrev.Stack.Used;
  451.             TmpCount++)
  452.         {
  453.             for(BufPtr = TmpBuffer;
  454.                 BufPtr = strstr(BufPtr, Abbrev.Stack.Data[TmpCount]);
  455.                 BufPtr++)
  456.             {
  457.                 CmdLen = strlen(Abbrev.Stack.Data[TmpCount]);
  458.                 Char = BufPtr[CmdLen];
  459.                 if(LATEX_SPACE(Char))
  460.                 {
  461.                     PrintError(RealBuf, (BufPtr - TmpBuffer) + CmdLen, 1, Line,
  462.                                 emInterWord);
  463.                 }
  464.             }
  465.         }
  466.  
  467.         /* Search for intersentence spacing */
  468.  
  469.         for(BufPtr = Buf;
  470.             TmpC = *BufPtr++;
  471.             )
  472.         {
  473.             if(isupper(TmpC) && LATEX_PUNCT(*BufPtr) && (LATEX_SPACE(BufPtr[1])))
  474.             {
  475.                 PrintError(RealBuf, BufPtr - Buf, 1, Line,
  476.                             emInterSent);
  477.             }
  478.         }
  479.  
  480.         /* Search for user-specified warnings */
  481.  
  482.         strcpy(TmpBuffer, Buf);
  483.  
  484. /*        strupr(TmpBuffer);
  485.  * we'll do things case-sensitive, for now.
  486.  */
  487.  
  488.         for(TmpCount = 0L;
  489.             TmpCount < UserWarn.Stack.Used;
  490.             TmpCount++)
  491.         {
  492.             CmdLen = strlen(UserWarn.Stack.Data[TmpCount]);
  493.             for(BufPtr = TmpBuffer;
  494.                 BufPtr = strstr(BufPtr, UserWarn.Stack.Data[TmpCount]);
  495.                 BufPtr++)
  496.             {
  497.                 PrintError(RealBuf, (BufPtr - TmpBuffer), CmdLen, Line,
  498.                             emUserWarn);
  499.             }
  500.         }
  501.     }
  502.  
  503.     return(TRUE);
  504. }
  505.  
  506. /*
  507.  * Scans the `Buf' for a LaTeX arg, and puts that arg into `Dest'. `Delim'
  508.  * is the leading character for the arg (either `{' or `[', that is).
  509.  * Returns NULL if we can't find the argument, ptr to `Dest' in other cases.
  510.  */
  511.  
  512. STRPTR GetLTXArg(STRPTR Buf, STRPTR Dest, const UBYTE Delim)
  513. {
  514.     UBYTE    mileD, TmpC;
  515.     STRPTR    Retval = NULL,
  516.             DDest = Dest;
  517.     ULONG    DeliCnt = 0L,
  518.             BufCnt = 0L;
  519.  
  520.     *Dest = 0L;
  521.  
  522.     if(mileD = MatchBracket(Delim))
  523.     {
  524.         while(TmpC = *Buf++)
  525.         {
  526.             if(!LATEX_SPACE(TmpC))
  527.                 break;
  528.         }
  529.  
  530.         if(TmpC == Delim)
  531.         {
  532.             DeliCnt++;
  533.             while(DeliCnt > 0L)
  534.             {
  535.                 TmpC = *Buf++;
  536.                 if(BufCnt++ < (BUFLEN - 1))
  537.                     *Dest++ = TmpC;
  538.                 else
  539.                     break;
  540.  
  541.                 if(TmpC == Delim)
  542.                     DeliCnt++;
  543.                 elif(TmpC == mileD)
  544.                     DeliCnt--;
  545.                 elif(!TmpC)
  546.                     break;
  547.             }
  548.             Retval = DDest;
  549.             *--Dest = 0L;
  550.         }
  551.         else
  552.         {
  553.             Dest[0] = TmpC;
  554.             Dest[1] = 0L;
  555.             Retval = DDest;
  556.         }
  557.     }
  558.     return(Retval);
  559. }
  560.  
  561.  
  562.  
  563. /*
  564.  * Prints and indicates the position of an error. Be sure that `String'
  565.  * does not contain tabs, newlines, etc.
  566.  */
  567.  
  568. #define PRINT_MESSAGE    va_start(MsgArgs, Error);                    \
  569.                         vfprintf(OutputFile, LaTeXMsgs[Error].Message, MsgArgs);        \
  570.                         va_end(MsgArgs)
  571.  
  572.  
  573. void PrintError(const STRPTR String, LONG Position, const LONG Len,
  574.                 const LONG Line, const enum ErrNum Error, ...)
  575. {
  576. static                                /* Just to reduce stack usage... */
  577.     UBYTE    PrintBuffer[BUFLEN];
  578.     va_list    MsgArgs;
  579.  
  580.  
  581.     if(betw(emMinFault, Error, emMaxFault) && LaTeXMsgs[Error].InUse)
  582.     {
  583.         switch(Verbosity)
  584.         {
  585.         case vbFancy:
  586.         case vbNormal:
  587.             if(String)
  588.             {
  589.                 strcpy(PrintBuffer, String);
  590.                 switch(LaTeXMsgs[Error].Type)
  591.                 {
  592.                 case etWarn:
  593.                     fprintf(OutputFile, "Warning %ld in line %ld: ", Error, Line);
  594.                     WarnPrint++;
  595.                     break;
  596.                 case etErr:
  597.                     fprintf(OutputFile, "Error %ld in line %ld: ", Error, Line);
  598.                     ErrPrint++;
  599.                     break;
  600.                 case etMsg:
  601.                     fprintf(OutputFile, "Message %ld in line %ld: ", Error, Line);
  602.                     break;
  603.                 }
  604.  
  605.                 PRINT_MESSAGE;
  606.                 fprintf(OutputFile, "\n");
  607.  
  608.                 if(Verbosity == vbNormal)
  609.                 {
  610.                     fprintf(OutputFile, "%s\n", strip(PrintBuffer, STRP_RGT));
  611.  
  612.                     sfmemset(PrintBuffer, ' ', (LONG) Position);
  613.  
  614.                     sfmemset(&PrintBuffer[Position], '^', Len);
  615.                     PrintBuffer[Position + Len] = 0;
  616.  
  617.                     fprintf(OutputFile, "%s\n", PrintBuffer);
  618.                 }
  619.                 else
  620.                 {
  621.                     strmid(String, PrintBuffer, 0L, Position);
  622.                     fputs(PrintBuffer, OutputFile);
  623.  
  624.                     strmid(String, PrintBuffer, Position, Len);
  625.                     ReverseVideo(PrintBuffer, OutputFile);
  626.  
  627.                     strmid(String, PrintBuffer, Position + Len, LONG_MAX);
  628.                     fputs(PrintBuffer, OutputFile);
  629.  
  630.                     fprintf(OutputFile, "\n\n");
  631.                 }
  632.             }
  633.             else
  634.             {
  635.                 switch(LaTeXMsgs[Error].Type)
  636.                 {
  637.                 case etWarn:
  638.                     fprintf(OutputFile, "General warning %ld: ", Error);
  639.                     WarnPrint++;
  640.                     break;
  641.                 case etErr:
  642.                     fprintf(OutputFile, "General error %ld: ", Error);
  643.                     ErrPrint++;
  644.                     break;
  645.                 case etMsg:
  646.                     fprintf(OutputFile, "General message %ld: ", Error);
  647.                     break;
  648.                 }
  649.                 PRINT_MESSAGE;
  650.                 fprintf(OutputFile, "\n");
  651.             }
  652.  
  653.             break;
  654.         case vbSilent:
  655.             fprintf(OutputFile, "%s%s%ld%s%ld%s%ld%s",
  656.                 InputName, Delimit,
  657.                 Line, Delimit,
  658.                 Position + 1, Delimit,
  659.                 Error, Delimit);
  660.  
  661.             PRINT_MESSAGE;
  662.             fprintf(OutputFile, "\n");
  663.             break;
  664.         }
  665.     }
  666.     else
  667.         UserSupp++;
  668.  
  669. }
  670. #undef PRINT_MESSAGE
  671.  
  672. /*
  673.  * All commands isolated is routed through this command, so we can
  674.  * update global statuses like math mode and whether @ is a letter
  675.  * or not.
  676.  */
  677.  
  678. void PerformCommand(const STRPTR Cmd)
  679. {
  680.     if(!strcmp(Cmd, "\\makeatletter"))
  681.         AtLetter = TRUE;
  682.     elif(!strcmp(Cmd, "\\makeatother"))
  683.         AtLetter = FALSE;
  684.     elif(*Cmd == '\\')
  685.     {
  686.         /* Quicker check of the commands \(, \[, \] and \). */
  687.         switch(Cmd[1])
  688.         {
  689.         case '(':
  690.         case '[':
  691.             MathMode = TRUE;
  692.             break;
  693.         case ']':
  694.         case ')':
  695.             MathMode = FALSE;
  696.             break;
  697.         }
  698.     }
  699. }
  700.  
  701.  
  702.  
  703.